﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using Infrastructure;
using Microsoft.Practices.Prism.Commands;
using Model;
using ViewsAndViewModels.Interfaces;

namespace ViewsAndViewModels.ViewModels
{
    public sealed class MainContentViewModel : ViewModelBase, IMainContentViewModel
    {
        private readonly IPasswordGenerator _generator;
        #region Bound Properties
        private string _errorText;
        [Description("Helpful text if the user cannot compute a password")]
        public string ErrorText
        {
            [DebuggerStepThrough]
            get { return _errorText; }
            [DebuggerStepThrough]
            set
            {
                if (value != _errorText)
                {
                    _errorText = value;
                    OnPropertyChanged("ErrorText");
                }
            }
        }
        private string _tip;
        [Description("General tool tip")]
        public string Tip
        {
            [DebuggerStepThrough]
            get { return _tip; }
            [DebuggerStepThrough]
            set
            {
                if (value != _tip)
                {
                    _tip = value;
                    OnPropertyChanged("Tip");
                }
            }
        }
        private int _passwordLength;
        [Description("The number of characters in the generated password; bound to the slider view")]
        public int PasswordLength
        {
            [DebuggerStepThrough]
            get { return _passwordLength; }
            [DebuggerStepThrough]
            set
            {
                if (value != _passwordLength)
                {
                    _passwordLength = value;
                    OnPropertyChanged("PasswordLength");
                    TryGenerate();
                    RaiseCommands();
                }
            }
        }
        private bool _isLeftHandChecked;
        [Description("If generated password will contain left-handed keys, bound to a checkbox")]
        public bool IsLeftHandChecked
        {
            [DebuggerStepThrough]
            get { return _isLeftHandChecked; }
            [DebuggerStepThrough]
            set
            {
                if (value != _isLeftHandChecked)
                {
                    _isLeftHandChecked = value;
                    OnPropertyChanged("IsLeftHandChecked");
                    TryGenerate();
                    RaiseCommands();
                }
            }
        }
        private bool _isRightHandChecked;
        [Description("If generated password will contain right-handed keys, bound to a checkbox")]
        public bool IsRightHandChecked
        {
            [DebuggerStepThrough]
            get { return _isRightHandChecked; }
            [DebuggerStepThrough]
            set
            {
                if (value != _isRightHandChecked)
                {
                    _isRightHandChecked = value;
                    OnPropertyChanged("IsRightHandChecked");
                    TryGenerate();
                    RaiseCommands();
                }
            }
        }
        private bool _isIncludeSymbolsChecked;
        [Description("If the generated password will contain symbols, bound to a checkbox")]
        public bool IsIncludeSymbolsChecked
        {
            [DebuggerStepThrough]
            get { return _isIncludeSymbolsChecked; }
            [DebuggerStepThrough]
            set
            {
                if (value != _isIncludeSymbolsChecked)
                {
                    _isIncludeSymbolsChecked = value;
                    OnPropertyChanged("IsIncludeSymbolsChecked");
                    TryGenerate();
                    RaiseCommands();
                }
            }
        }
        private string _computedPassword;
        [Description("Final value of the generated password, bound to a textbox")]
        public string ComputedPassword
        {
            [DebuggerStepThrough]
            get { return _computedPassword; }
            [DebuggerStepThrough]
            set
            {
                if (value != _computedPassword)
                {
                    _computedPassword = value;
                    OnPropertyChanged("ComputedPassword");
                }
            }
        }
        #endregion
        #region Commanding
        public DelegateCommand CopyToClipboardCommand { get; private set; }
        public DelegateCommand SaveToFileCommand { get; private set; }
        public DelegateCommand RegenerateCommand { get; private set; }
        private bool CanCompute()
        {
            if (IsLeftHandChecked || IsRightHandChecked) return true;
            return false;
        }
        private void ExecuteRegenerateCommand()
        {
            TryGenerate();
        }
        private bool CanExecuteRegenerateCommand()
        {
            return CanCompute();
        }
        private void ExecuteSaveToFileCommand(){}
        private bool CanExecuteSaveToFileCommand()
        {
            //if (ComputedPassword.Length > 0) return true; // next release
            return false;
        }
        private void ExecuteCopyToClipboardCommand()
        {
            Clipboard.SetText(ComputedPassword);
        }
        private bool CanExecuteCopyToClipboardCommand()
        {
            if (ComputedPassword.Length > 0) return true;
            return false;
        }
        private void RaiseCommands()
        {
            if (CopyToClipboardCommand != null) CopyToClipboardCommand.RaiseCanExecuteChanged();
            if (SaveToFileCommand != null) SaveToFileCommand.RaiseCanExecuteChanged();
            if (RegenerateCommand != null) RegenerateCommand.RaiseCanExecuteChanged();
        }
        #endregion
        public  MainContentViewModel(IMainContentView view, IPasswordGenerator generator) :base(view)
        {
            _generator = generator;
            CopyToClipboardCommand = new DelegateCommand(ExecuteCopyToClipboardCommand, CanExecuteCopyToClipboardCommand);
            SaveToFileCommand = new DelegateCommand(ExecuteSaveToFileCommand, CanExecuteSaveToFileCommand);
            RegenerateCommand = new DelegateCommand(ExecuteRegenerateCommand, CanExecuteRegenerateCommand);
            PasswordLength = 4;
            ComputedPassword = string.Empty;
            IsLeftHandChecked = true;
            ErrorText = String.Empty;
            TryGenerate();
        }
        private void TryGenerate()
        {
            ComputedPassword = String.Empty;
            ErrorText = Tip = String.Empty;
            if (CanCompute())
            {
                PasswordGenerationInfo info = new PasswordGenerationInfo
                    {
                        Length = PasswordLength,
                        UseLeftHand = IsLeftHandChecked,
                        UseRightHand = IsRightHandChecked,
                        UseSymbols = IsIncludeSymbolsChecked
                    };
                ComputedPassword = _generator.GeneratePassword(info);
            }
            else
            {
                Tip = "Cannot compute a new password.  Please select a checkbox...";
                ErrorText = Tip;
            }
        }
    }
}
